/*
 * SystemServer.cpp
 *
 *  Created on: 2021年9月6日
 *      Author: vicent-PC
 */
#define LOG_TAG "SystemServer"
#include "SystemServer.h"

#include "esp_err.h"
#include "esp_event.h"
#include "esp_log.h"
#include "esp_spi_flash.h"
#include "esp_system.h"
#include "esp_wifi.h"
#include "esp_timer.h"

#include "freertos/FreeRTOS.h"
#include "freertos/task.h"

#include <thread>
#include <mutex>
#include <condition_variable>

#include <Trace.h>

std::mutex m;
std::condition_variable cv;
bool gHwSyncReady = false;

SystemServer *SystemServer::m_pInstance = nullptr;

SystemServer::SystemServer() {
    // TODO Auto-generated constructor stub
}

SystemServer::~SystemServer() {
    // TODO Auto-generated destructor stub
}

void SystemServer::dispatchKeyEvent() {
    TRACE_B();
    mForeActivity->onEvent();
}

void SystemServer::registerEventListener(Activity &activity) {
    TRACE_B();
    mpInputEventMgr->registerReciever(mForeActivity);
}

void SystemServer::activeFG_ActivityEventListener() {
    TRACE_B();
    mpInputEventMgr->registerReciever(mForeActivity);
}

void sendHWsyncReqSignal() {
    {
        std::lock_guard<std::mutex> lk(m);
        gHwSyncReady = true;
        // LOGI("gene HW sync Signal");
    }
    cv.notify_one();
}

void SystemServer::startActivity(Activity *activity) {
    TRACE_B();
    LOGD("%s() activity status:%d", __func__, activity->getStatus());
    if (ACTIVITY_NOTCREATE == activity->getStatus()) {
        activity->onCreate();
        activity->updateStatus(ACTIVITY_STOPED);
    }
    if (ACTIVITY_STOPED == activity->getStatus()) {
        activity->onStart();
        activity->updateStatus(ACTIVITY_PAUSED);
    }
    if (ACTIVITY_PAUSED == activity->getStatus()) {
        // Pause Current activity
        if (mForeActivity != nullptr
            && ACTIVITY_RUNING == mForeActivity->getStatus()) {
            mForeActivity->onPause();
            mForeActivity->updateStatus(ACTIVITY_PAUSED);
        }
        // Active new activity to running status
        activity->onResume();
        activity->updateStatus(ACTIVITY_RUNING);
        mForeActivity = activity;
        activeFG_ActivityEventListener();

        // Notify foreActivity update
        sendHWsyncReqSignal();  // manul trigger hw sync
    }
    if (ACTIVITY_PAUSED == activity->getStatus()) {
        activity->onResume();
        activity->updateStatus(ACTIVITY_RUNING);
    }
}

void SystemServer::registerEventSrc(InputEventMgr *pInputEventMgr) {
    mpInputEventMgr = pInputEventMgr;
}

void SystemServer::swSyncLoop2(void *param) {
    if (nullptr == param) {
        LOGE("%s param nullptr", __func__);
    }

    SystemServer *server = (SystemServer *)param;
    while (server->mSwSyncEnable) {
        // Wait Signal
        std::unique_lock<std::mutex> lk(m);
        cv.wait(lk, []{return gHwSyncReady;});
        gHwSyncReady = false;
        // LOGI("recv HW sync Signal");
        if (ACTIVITY_RUNING == server->mForeActivity->getStatus()) {
            server->mForeActivity->onDraw();
        }
    }
    vTaskDelete(NULL);
}

void timer_cb(void *arg) {
    sendHWsyncReqSignal();
}

void SystemServer::startSWsyncThread() {
    mSwSyncEnable = true;
    int ret = xTaskCreate(SystemServer::swSyncLoop2, /* Task function. */
                          "swSyncLoop2", /* String with name of task. */
                          8192,          /* Stack size in bytes. */
                          this,  /* Parameter passed as input of the task */
                          0,     /* Priority of the task. */
                          NULL); /* Task handle. */
    if (ret != pdPASS) {
        LOGE("SWsync start fail:%d", ret);
    }

    esp_timer_create_args_t hw_timer = {
        .callback = &timer_cb,
        .arg = NULL,
        .name = "hw_timer"
    };

    mTimerHandler = malloc(sizeof(esp_timer_handle_t));
    esp_timer_handle_t* ptimer_handle = (esp_timer_handle_t*)mTimerHandler;
    ret = esp_timer_create(&hw_timer, ptimer_handle);
    ret = esp_timer_start_periodic(*ptimer_handle, 1000 * 1000 / mSwSyncFps);    // 1s = 1000*1000
    if (ret != 0) {
        LOGI("fw timer cteate and start ok!");
    }
}

void SystemServer::stopSWsyncThread() {
    mSwSyncEnable = false;
    if (mTimerHandler != nullptr) {
        esp_timer_handle_t* ptimer_handle = (esp_timer_handle_t*)mTimerHandler;
        esp_timer_stop(*ptimer_handle);
        esp_timer_delete(*ptimer_handle);
        free(mTimerHandler);
        mTimerHandler = nullptr;
    }
    // send last signal to exit
    sendHWsyncReqSignal();
}
